/*******************************************************************************
 Copyright (c) 2010 Koninklijke Philips N.V.,
 All Rights Reserved.
 
 File name: fsm.c
 Description: Source file for the finite state machine component, and provide the utility 
			  functions for the use of FSM in the system.
 Project: XXX
 Component name: FSM 
 $LastChangedDate:  $
 $Revision:  $
 $Author:  $
 Lighting GBU CFLi
 
 This source code and any compilation or derivative thereof is the
 proprietary information of Koninklijke Philips N.V.
 and is confidential in nature.
 Under no circumstances is this software to be combined with any Open Source
 Software in any way or placed under an Open Source License of any type without
 the express written permission of Koninklijke Philips N.V.
*******************************************************************************/

/****************************************************************************************
* INCLUDE FILES
****************************************************************************************/
#include "fsm.h"

/****************************************************************************************
* LOCAL CONSTANTS
****************************************************************************************/
#define     FSM_HISTORY_MAX   (64)

/****************************************************************************************
* LOCAL TYPEDEFS
****************************************************************************************/

/****************************************************************************************
* LOCAL VARIABLES
****************************************************************************************/
static uint8    __fsm_initialized = FALSE;
static fsm_handle_t*    __fsm_handles[3];

/****************************************************************************************
* GLOBAL VARIABLES
****************************************************************************************/

/****************************************************************************************
* LOCAL FUNCTIONS PROTOTYPE
****************************************************************************************/

/****************************************************************************************
* LOCAL MACRO
****************************************************************************************/

/****************************************************************************************
* GLOBAL FUNCTIONS
****************************************************************************************/

void fsm_init(void)
{
    if (__fsm_initialized == FALSE)
    {
        __fsm_initialized = TRUE;
    }   
}

uint8  fsm_create(
    fsm_handle_t        *p_fsm_handle,
    uint8               module_id,
    uint8               init_state,
    CODE fsm_table_t    *p_table,
    uint8               table_size
)
{
    fsm_handle_t   local;

    local.current_state  = init_state;
    local.module_id        = module_id;
    local.p_table    = p_table;
    local.table_size = table_size;
    *p_fsm_handle = local;

    __fsm_handles[module_id] = p_fsm_handle;
    
    return TRUE;
}

uint8  fsm_evaluate(uint8 module_id, uint8 event)
{
    CODE fsm_table_t     *p_table_entry;
    fsm_handle_t         *p_fsm_handle;
    uint8       table_size;
    uint8       index = 0;
    uint8             found = FALSE;
    CODE void *         p_temp;

    p_fsm_handle = __fsm_handles[module_id];
    table_size = p_fsm_handle->table_size;

    // search table until found
    while ((found == FALSE) && table_size)
    {
        // get an entry pointer to current record
        table_size--;
        p_table_entry = &(p_fsm_handle->p_table[index++]);
        p_temp   = &(p_table_entry->condition_func);
        
        // search for record with:
        //  - same event
        //  - correct current state (or 0)
        //  - conditional function returns TRUE (or no cond. function)
        if (    
                ( p_table_entry->event==event ) &&
                ((p_table_entry->current_state==ALL_STATES)||
                (p_table_entry->current_state == p_fsm_handle->current_state)) &&
                ((*(CODE int *)p_temp == 0) || (p_table_entry->condition_func()) )
           )
        {
           // OKAY: found valid fsm entry
            found = TRUE;
           
            p_temp = &(p_table_entry->pfvActionFunction);
            if (*(CODE int*)p_temp!= 0)
            {
                p_table_entry->pfvActionFunction();
            }
    
            // change state
            if (p_table_entry->next_state!=SAME_STATE)
            {
                p_fsm_handle->current_state = p_table_entry->next_state;
            }
        }
    }

    return(found);
}


/****************************************************************************************
* LOCAL FUNCTIONS
****************************************************************************************/



/*****************************************************************************/

